﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DotHandler
{
    public class Fila<T> : Colecao<T>
    {
        #region Construtor
        public Fila(uint size)
            : base(size)
        {
            this._index = new int[2];
            this._index[0] = 0;
            this._index[1] = -1;
        }
        #endregion

        #region Interação
        /*******************************************************************/
        public void Enqueue(dynamic o, Boolean identity=true)
        {
            if (!this.IsFull())
            {
                _index[1] += 1;
                int pos = (int)(_index[1] % Size);
                this._storage[pos] = o;
                if (identity)
                {
                    o.Identity(this.identity);
                    this.identity += 1;
                }
            }
            else
            {
                throw new Exception("Full queue");
            }
        }
        public void Enqueue(Boolean multiple, params dynamic[] o)
        {
            foreach (var item in o)
            {
                this.Enqueue(item);
            }
        }

        public dynamic Dequeue()
        {
            if (!this.IsEmpty())
            {
                int pos = (int)(_index[0] % Size);
                _index[0] += 1;
                return this._storage[pos];
            }
            throw new Exception("Empty queue");
        }

        public dynamic[] Dequeue(Boolean multiple, int qtd)
        {
            if(qtd<=(this.Index+1))
            {
                dynamic [] retorno = new dynamic[qtd];
                for(var i = 0;i<qtd;i+=1)
                {
                    retorno[i] = Dequeue();
                }
                return retorno;
            }
            throw new NullReferenceException();
        }
        /*******************************************************************/
        #endregion 

        public override int Index
        {
            get
            {
                return (_index[1] % Size);
            }
        }

        public override int Quantity
        {
            get
            {
                return Math.Abs((_index[1] - _index[0]) + 1);
            }
        }

        public new void Sort(string property = null)
        {
            _index[0] = 0;
            _index[1] = (Quantity - 1);
            int index = 0;
            Each((o) =>
            {
                _storage[index] = o;
                index += 1;
                return true;
            });
            base.Sort();
        }
        
        public override void Each(Func<dynamic, bool> handler)
        {
            for (var s = _index[0]; s <= _index[1]; s += 1)
            {
                if (handler(_storage[s % Size])==false)
                {
                    break;
                }
            }
        }

        public override bool IsFull()
        {
            if (this.Quantity >= this.Size)
            {
                return true;
            }
            return false;
        }

        public override bool IsEmpty()
        {
            if (this._index[0] > this._index[1])
            {
                return true;
            }
            return false;
        }

        public new T Find(String property, String value)
        {
            value = value.ToLower();
            int i;
            for (i = _index[0]; i <= _index[1]; i += 1)
            {
                var j = i % Size;
                var t = _storage[j].ToString(property);
                if (t == value)
                {
                    return _storage[j];
                }
            }
            return default(T);
        }

        public new Lista<T> Find(bool multiple, String property, String value)
        {
            Lista<T> resultset = new Lista<T>((uint)this.Size);
            value = value.ToLower();
            int i;
            for (i = _index[0]; i <= _index[1]; i += 1)
            {
                var j = i % Size;
                var t = _storage[j].ToString(property);
                if (t == value)
                {
                    resultset.Add(_storage[j]);
                }
            }
            return (resultset.Quantity>0)?resultset:null;
        }

        public override void Destroy()
        {
            this._index[0] = 0;
            this._index[1] = -1;  
        }
    }
}
